(** Module Main
 *
 *  Author: Jk
 *)

open IL
open Misc
open Settings


exception Invalid_generator of string

let knownGenerators = 
   [ "ostap", (GenOstap.registerOptions, GenOstap.generator)
   ; "glr"  , (GenGLR.options, GenGLR.generator)
   ; "html" , (DumpHTML.options, DumpHTML.generator)
   ; "text" , (GenText.options, GenText.generator)
   ]

let findGenerator name =
    try 
      List.assoc name knownGenerators
    with 
      Not_found -> raise (Invalid_generator name)
 
let options opts = customize opts
   [ "gen", String, Mandatory, Printf.sprintf 
                               " <gen>\t - generator name, one of [%s]" 
                               (String.concat ", " (List.map fst knownGenerators))
   ; "v",Switch,Mandatory, "\t - display version and exit"
   ; "help",Switch,Mandatory, "\t - print this help and exit"
   ]
   (fun () -> [])

let parseAndGenerate ichan generator =
  let lexbuf = Lexing.from_channel ichan in
  try 
     let g =  Parser.file Lexer.main lexbuf in
     generator g
  with
     Parsing.Parse_error -> 
     let pos = lexbuf.Lexing.lex_start_p in
     let str = "Syntax error" in 
     Printf.printf "%s at line %d" str pos.Lexing.pos_lnum
  
let _ = 
  let version =  Printf.sprintf "YARD tool -- %s" Version.version in
  let yard_help conf = Printf.sprintf "%s\nUsage:\n%s" version (conf.help ()) in
  let argsList = List.tl (Array.to_list Sys.argv) in
  match options (Settings.empty ()) argsList with 
  | Warnings (_,_,w)  -> Printf.printf "Incorrect options:\n %s" (String.concat "\n" w);exit 1
  | Ok (conf,_) ->  
     match conf.get "v" with  
     | Some _ -> print_endline version
     | None -> match conf.get "help" with 
       | Some _ -> print_endline (yard_help conf)
	     | None   ->      
         try 
           let generatorName = String.lowercase (getMandatoryStringOption conf "gen") in
           let (options',generator) = findGenerator generatorName in
           match  options options' argsList with           
           Ok(conf,rest) ->
    	     let ichan = open_in_bin (List.hd rest) in
             let result = parseAndGenerate ichan (generator conf) in 
             let () = close_in ichan in
             result
          | _ -> ()

         with 
           MissingOption (o, conf) -> 
           (Printf.printf "Missing option `-%s'\n%s\n" o (yard_help conf)
           ; exit 1
           )           
